package com.mysteel.monitor.core.command;


import com.mysteel.monitor.core.model.ThreadMonitorInfo;
import com.mysteel.monitor.core.model.ThreadOverview;
import com.mysteel.monitor.core.utils.ArrayUtils;
import com.mysteel.monitor.core.utils.ThreadRenderUitl;
import com.mysteel.monitor.core.utils.ThreadUtil;

import java.lang.Thread.State;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.*;

/**
 * @author Administrator
 */
public class ThreadCommand  {

    private static Set<String> states = null;
    private static ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
    private long id = -1;
    private Integer topNBusy = null;
    private boolean findMostBlockingThread = false;
    private int sampleInterval = 100;
    private String state;

    {
        states = new HashSet<String>(State.values().length);
        for (State state : State.values()) {
            states.add(state.name());
        }
    }

    public void setId(long id) {
        this.id = id;
    }


    public void setTopNBusy(Integer topNBusy) {
        this.topNBusy = topNBusy;
    }


    public void setFindMostBlockingThread(boolean findMostBlockingThread) {
        this.findMostBlockingThread = findMostBlockingThread;
    }


    public void setSampleInterval(int sampleInterval) {
        this.sampleInterval = sampleInterval;
    }


    public void setState(String state) {
        this.state = state;
    }

    public void process() {
        int status = 0;
        try {
            if (id > 0) {
                // 处理指定的tomcat
                status = processThread();
            } else if (topNBusy != null) {
//                status = processTopBusyThreads();
            } else if (findMostBlockingThread) {
                 processBlockingThread();
            } else {
//                status = processAllThreads();
            }
        } finally {

        }
    }

    /**
     *  线程总览
     * @return
     */
    public ThreadOverview processAllThreads() {
        ThreadOverview overview = new ThreadOverview();
        Map<String, Integer> totalMap = new LinkedHashMap<>();

        Map<String, Thread> threads = ThreadUtil.getThreads();
        // 统计各种线程状态
        StringBuilder threadStat = new StringBuilder();
        Map<State, Integer> stateCountMap = new HashMap<State, Integer>();

        for (State s : State.values()) {
            stateCountMap.put(s, 0);
        }

        for (Thread thread : threads.values()) {
            State threadState = thread.getState();
            Integer count = stateCountMap.get(threadState);
            stateCountMap.put(threadState, count + 1);
        }
        totalMap.put("Threads Total: ",threads.values().size());
        for (State s : State.values()) {
            Integer count = stateCountMap.get(s);
            // 添加头部信息
            totalMap.put(s.name(),count);
        }

        Collection<Thread> resultThreads = new ArrayList<Thread>();
        if (this.state != null && this.state.trim() != ""){
            this.state = this.state.toUpperCase();
            if(states.contains(this.state)) {
                for (Thread thread : threads.values()) {
                    if (state.equals(thread.getState().name())) {
                        resultThreads.add(thread);
                    }
                }
            }else{
            }
        } else {
            resultThreads = threads.values();
        }
         List<ThreadMonitorInfo> monitorInfos = ThreadRenderUitl.renderer(resultThreads.iterator());
        overview.setTotal(totalMap);
        overview.setThreadInfos(monitorInfos);
        return overview;
    }

    public String processBlockingThread() {
        String stacktrace =null;
        ThreadUtil.BlockingLockInfo blockingLockInfo = ThreadUtil.findMostBlockingLock();
        if (blockingLockInfo.threadInfo == null) {
            stacktrace = "当前无阻塞线程";
        } else {
             stacktrace = ThreadUtil.getFullStacktrace(blockingLockInfo);
        }
        return stacktrace;
    }

    /**
     * 最繁忙的线程
     * @param topNBusy
     * @return
     */
    public List<String>  processTopBusyThreads(int topNBusy) {
        List<String> stacktraceList = new ArrayList<>();
        Map<Long, Long> topNThreads = ThreadUtil.getTopNThreads(sampleInterval, topNBusy);
        Long[] tids = topNThreads.keySet().toArray(new Long[0]);
        ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(ArrayUtils.toPrimitive(tids), true, true);
        if (threadInfos == null) {
        } else {
            for (ThreadInfo info : threadInfos) {
                 stacktraceList.add(ThreadUtil.getFullStacktrace(info, topNThreads.get(info.getThreadId())));
            }
        }
        return stacktraceList;
    }

    private int processThread() {
        int status = 0;
        String content;
        ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(new long[]{id}, true, true);
        if (threadInfos == null || threadInfos[0] == null) {
            content = "thread do not exist! id: " + id + "\n";
            status = 1;
        } else {
            // no cpu usage info
            content = ThreadUtil.getFullStacktrace(threadInfos[0], -1);
        }
        return status;
    }
}